/*
    日志功能
*/

#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <unistd.h>

namespace JsonMuduoRPC
{
    // 日志等级
    enum
    {
        DEBUG = 0,
        INFO,
        WARNING,
        ERROR,
        FATAL
    };

    const char *log_path = "./log.txt"; // 日志文件默认路径
    bool is_save_to_file = false;       // 是否将日志打印到文件
    int print_level = DEBUG;            // 高于print_level等级再打印日志

    void saveLogToFile(const char *log_massage)
    {
        FILE *fp = fopen(log_path, "a");
        if (nullptr == fp)
        {
            perror("fopen");
            exit(FATAL);
        }

        fseek(fp, 0, SEEK_END);
        fprintf(fp, "%s", log_massage);
        fclose(fp);
    }

    const std::string getLevelStr(int level)
    {
        switch (level)
        {
        case DEBUG:
            return "DEBUG";
        case INFO:
            return "INFO";
        case WARNING:
            return "WARING";
        case ERROR:
            return "ERROR";
        case FATAL:
            return "FATAL";
        default:
            return "UNKNOW";
        }
    }

    // 获取当前时间 年-月-日 时:分:秒
    const std::string getNowTimeStr()
    {
        time_t time_stamp = time(nullptr);
        struct tm *s_time = localtime(&time_stamp);
        char buffer[60]{0};
        strftime(buffer, sizeof(buffer) - 1, "%Y-%m-%d %H:%M:%S", s_time);

        return buffer;
    }

    // 打印日志信息
    void logMassage(const int level, const char *file, const int line, const char *format, ...)
    {
        std::string time_str = getNowTimeStr();
        std::string level_str = getLevelStr(level);

        // 获取可变参数内容
        char va[1024];
        va_list ap;
        va_start(ap, format);
        vsnprintf(va, sizeof(va) - 1, format, ap);
        va_end(ap);

        const std::string log_massage = "[" + level_str + "]" + "[" + file + ":" + std::to_string(line) + "]" +
                                        "[pid:" + std::to_string(getpid()) + "]" +
                                        "[" + time_str + "]" + "[" + va + "]" + "\n";

        if (is_save_to_file)
            saveLogToFile(log_massage.c_str());
        else
            std::cout << log_massage << std::endl;
    }

#define LOG(level, format, ...)                                           \
    do                                                                    \
    {                                                                     \
        if (level >= JsonMuduoRPC::print_level)                           \
        {                                                                 \
            logMassage(level, __FILE__, __LINE__, format, ##__VA_ARGS__); \
        }                                                                 \
                                                                          \
    } while (0)

} // namespace JsonMuduoRPC
